package com.bjsdzk.collector.controller;

import cmcciot.onenet.nbapi.sdk.api.online.ExecuteOpe;
import cmcciot.onenet.nbapi.sdk.entity.Execute;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bjsdzk.backend.rpc.OnetService;
import com.bjsdzk.backend.rpc.before.OneNETbefore;
import com.bjsdzk.backend.rpc.entity.OneNetCallBackResult;
import com.bjsdzk.collector.constant.Constant;
import com.bjsdzk.collector.dao.TemperatureDao;
import com.bjsdzk.collector.entity.Temperature;
import com.bjsdzk.collector.entity.model.Dictionaries;
import com.bjsdzk.collector.entity.model.ExceColleContr;
import com.bjsdzk.collector.entity.model.ParamsSetting;
import com.bjsdzk.collector.rpc.OneNetCollectService;
import com.bjsdzk.collector.serviceImp.DictionariesService;
import com.bjsdzk.collector.serviceImp.ExceColleContrService;
import com.bjsdzk.collector.serviceImp.ParamsSettingService;
import com.bjsdzk.collector.utils.OkHttpCli;
import com.bjsdzk.collector.utils.OneNetUtil;

import com.bjsdzk.collector.utils.TimeUtil;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.mongo.BulkOperation;
import io.vertx.ext.mongo.MongoClient;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.json.JSONArray;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/oneNet")
public class OneNetReceiverController {

	private static final Logger logger = LoggerFactory.getLogger(OneNetReceiverController.class);
    private static String token ="bjsdzkTemperature";//用户自定义token和OneNet第三方平台配置里的token一致
    private static String aeskey ="whBx2ZwAU5LOHVimPj1MPx56QRe3OsGGWRe4dr17crV";//aeskey和OneNet第三方平台配置里的token一致
    private static final  String kwyapiKey="qFutuQ3Lhs0umBxivZcYRt5mdmA=";
    private static final  String POST_ALARM="POST-ALARM";
    private static final  String POST_ALARM_DATA="POST-ALARM-DATA";
    private static final  String POST_WARN="POST-WARN";
    private static final  String POST_WARN_DATA="POST-WARN-DATA";
    private static final  String POST_REALTIME="POST-REALTIME";

    @Autowired
    private TemperatureDao temperatureDao;
    @Reference( check = false,version ="1.0.0",lazy=true)
    private OnetService onetService;
    @Autowired
    private OneNetCollectService oneNetCollectService;
    @Autowired
    private OkHttpCli okHttpCli;
    @Autowired
    private MongoClient mongoClient;
    @Autowired
    private ExceColleContrService exceColleContrService;
    @Autowired
    private ParamsSettingService paramsSettingService;
    @Autowired
    private DictionariesService dictionariesService;
    @Reference( check = false,version ="1.0.0",lazy=true,retries = 1,group = Constant.GROUP_PLATFORM)
    private OneNETbefore oneNETbefore;
    @Reference( check = false,version ="1.0.0",lazy=true,retries = 1,group = Constant.GROUP_APP)
    private OneNETbefore aPPoneNETbefore;


    /**
     * 功能描述：第三方平台数据接收。<p>
     *           <ul>注:
     *               <li>1.OneNet平台为了保证数据不丢失，有重发机制，如果重复数据对业务有影响，数据接收端需要对重复数据进行排除重复处理。</li>
     *               <li>2.OneNet每一次post数据请求后，等待客户端的响应都设有时限，在规定时限内没有收到响应会认为发送失败。
     *                    接收程序接收到数据时，尽量先缓存起来，再做业务逻辑处理。</li>
     *           </ul>
     * @param body 数据消息
     * @return 任意字符串。OneNet平台接收到http 200的响应，才会认为数据推送成功，否则会重发。
     */
    @PostMapping("/temperatur")
    public String receive(@RequestBody String body) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {

        OneNetUtil.BodyObj resutl;
        if((resutl=plain(body))!=null){
            JSONObject jsonObject = JSON.parseObject(resutl.getMsg().toString());
            logger.info("onenet数据：" + jsonObject.toJSONString());
            jsonObject.put("createAt", TimeUtil.getCurrentDatetime());
            Temperature stu = jsonObject.toJavaObject(Temperature.class);
            temperatureDao.save(stu);
            onetService.data(jsonObject.toJSONString());
            logger.info("onenet数据：" + "成功");
        }
        return "ok";
    }

    /**
     * 功能说明： URL&Token验证接口。如果验证成功返回msg的值，否则返回其他值。
     * @param msg 验证消息
     * @param nonce 随机串
     * @param signature 签名
     * @return msg值
     */

    @GetMapping("/temperatur")
    public String check(@RequestParam(value = "msg") String msg,
                        @RequestParam(value = "nonce") String nonce,
                        @RequestParam(value = "signature") String signature) throws UnsupportedEncodingException {
        return chec(msg, nonce, signature);
    }

    @GetMapping("/createDevice")
    public void createDevice(String imei,String imsi,String name)  throws Exception {
        JsonObject params = new JsonObject();
        params.put("imei", imei);
        params.put("imsi", imsi);
        params.put("name", name);
        params.put("deviceType", "SMOKE");
        oneNetCollectService.deviceAdd(params.toString());
    }

    @GetMapping("/deleteDevice")
    public void deleteDevice(String deveiceId)  throws Exception {
        JsonObject params = new JsonObject();
        params.put("deveiceId", deveiceId);
        params.put("deviceType", "SMOKE");
        oneNetCollectService.deviceDelete(params.toString());
    }

    @GetMapping("/lookDevice")
    public void lookDevice(String deveiceId)  throws Exception {
        JsonObject params = new JsonObject();
        params.put("deveiceId", deveiceId);
        params.put("deviceType", "SMOKE");
        oneNetCollectService.lookDevice(params.toString());
    }


    @GetMapping("/onea")
    public void onea()  throws Exception {
        StringBuilder sb = new StringBuilder("KW|KAIWAN|460042567812043&869975030507381");
        sb.append("|F1|01-02-10-10|03|01|2-20.3|04|01|4-10|");
        String crc = CRC_XModem(sb.toString().getBytes());
        sb.append(crc);
        logger.info(sb.toString() + "---------------------------------------------------------");
        String[] ds_id = "3200_0_5750".split("_");

        ExecuteOpe executeOpe = new ExecuteOpe(kwyapiKey);
        Execute execute = new Execute("869975030507381", Integer.parseInt(ds_id[0]), Integer.parseInt(ds_id[1]), Integer.parseInt(ds_id[2]));
        org.json.JSONObject params = new org.json.JSONObject();
        params.put("args", sb.toString());
        logger.info(executeOpe.operation(execute, params).toString());
    }

    public void asdfd()  throws Exception {
//        oneNetCollectService.executeCmd();
    }

    @GetMapping("/tuobaoyangan")
    public String tuobaoyangan(@RequestParam(value = "msg") String msg,
                            @RequestParam(value = "nonce") String nonce,
                            @RequestParam(value = "signature") String signature) throws UnsupportedEncodingException {
        return chec(msg, nonce, signature);
    }

    @PostMapping("/tuobaoyangan")
    public String tuobaoyanganpost(@RequestBody String body)  throws JSONException {
        OneNetUtil.BodyObj resutl;
        if ((resutl = plain(body)) != null) {
//            { "msg":{"at":1575341237362,"imei":"869029035964237","type":1,"ds_id":"3200_0_5750","value":"7E015DE5CCAA000200290100650808690290359642376901B71702000C66080460042688001263160C00000020000000000000000EB6C87E","dev_id":574268700}，"nonce":htw0BM_K，"signature":yVfTQS3vVTGc3VX1tDQVAw==}
//            { "msg":{"at":1575340985822,"login_type":10,"imei":"869029035964237","type":2,"dev_id":574268700,"status":1}
            JSONObject json = JSON.parseObject(resutl.getMsg().toString());
            String imei = json.getString("imei");
            String dev_id = json.getString("dev_id");
            String at = TimeUtil.parseTime(LocalDateTime.ofEpochSecond(json.getLong("at"), 0, ZoneOffset.ofHours(8)));
            Date date = Date.from(LocalDateTime.ofEpochSecond(json.getLong("at"), 0, ZoneOffset.ofHours(8)).atZone(ZoneId.systemDefault()).toInstant());
            if (json.getInteger("type") == 2) {
                logger.info(json.getInteger("status")+"");
//                onetService.status(imei, dev_id, date, json.getInteger("status"));
                return "ok";
            }
            if (json.getInteger("type") == 7) {
                return "ok";
            }

            String value = json.getString("value");
            if (value.startsWith("7E") && value.endsWith("7E")) {
                String version = value.substring(2, 4);//版本
                int time = Integer.parseInt(value.substring(4, 12), 16);//时间
                String num = value.substring(12, 16);//帧号
                int len = Integer.parseInt(value.substring(16, 20), 16);//长度
                String cm = value.substring(20, 22);//指令
                String pw = value.substring(22, 24);//加密
                if(StringUtils.equals(cm, "02")){
                    StringBuilder sb=new StringBuilder("7E01");
                    sb.append(String.format("%08x",System.currentTimeMillis()/1000));
                    sb.append("0000");
                    sb.append("000A");
                    sb.append("02");
                    sb.append("00");
                    sb.append("65");
                    sb.append("08");
                    sb.append(String.format("%016d",Long.parseLong(imei)));
                    sb.append("0000");
                    sb.append("7E");
                    try {
                       oneNetCollectService.executeCmd(sb.toString(), imei, "BAREN_SMOKE");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return "ok";
                }

                int i = 24;
                org.json.JSONObject result = new org.json.JSONObject();
                result.put("version", version);
                result.put("time", time);
                result.put("num", num);
                result.put("len", len);
                result.put("cm", cm);
                result.put("pw", pw);
                JSONArray arr = new JSONArray();
                while (i < len * 2) {
                    String type = value.substring(i, i + 2);
                    int l = Integer.parseInt(value.substring(i + 2, i + 4), 16);
                    String typeValue = value.substring(i + 4, i = i + 4 + l * 2);
                    String conent = "";

                    switch (type) {
                        case "65":
                            conent = "设备唯一标识码:" + typeValue;
                            break;
                        case "69":
                            conent = "NB 信号质量:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "17":
                            conent = "发送失败帧计数:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "14":
                            conent = "烟雾浓度值:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "0B":
                            conent = "温度值:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "24":
                            conent = "电池百分比:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "6C":
                            conent = "参考信号接收功率:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "6D":
                            conent = "信噪比:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "6E":
                            conent = "物理小区标识:" + typeValue;
                            break;
                        case "6F":
                            conent = "NB 模组网络质量打分值，覆盖等级，模组自动划分:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "70":
                            conent = "SIM 卡 ID:" + typeValue;
                            break;
                        case "71":
                            conent = "小区 ID:" + typeValue;
                            break;
                        case "19":
                            conent = "设备自检:" + typeValue;
                            break;
                        case "01":
                            if (StringUtils.equals(typeValue, "01")) {
                                conent = "火灾报警";
                            } else if (StringUtils.equals(typeValue, "02")) {
                                conent = "温度报警";
                            }
                            break;
                        case "02":
                            if (StringUtils.equals(typeValue, "02")) {
                                conent = "烟感电量低";
                            } else if (StringUtils.equals(typeValue, "03")) {
                                conent = "防拆报警";
                            } else if (StringUtils.equals(typeValue, "07")) {
                                conent = "发射电路故障";
                            }
                            break;

                        case "67":
                            conent = "通信模组软件版本";
                            break;
                        case "68":
                            conent = "NB 模块厂商编号";
                            break;
                        case "03":
                            conent = "终端类型";
                            break;
                        case "05":
                            String s = Integer.toBinaryString(Integer.parseInt(typeValue));
                            if (s.length() > 4) {
                                int begin = s.length() - 4;
                                conent = "硬件版本:" + s.substring(0, begin) + ",软件版本:" + s.substring(begin);
                            } else {
                                conent = "硬件版本:" + 000 + ",软件版本:" + s;
                            }
                            break;
                        case "06":
                            conent = "正常工作时间间隔:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "08":
                            conent = "紧急报警间隔范围:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "09":
                            conent = "一般报警间隔:" + Integer.parseInt(typeValue, 16);
                            break;
                        case "21":
                            conent = "温度报警值(下限):" + Integer.parseInt(typeValue, 16);
                            break;

                        default:
                            System.out.println(type);
                    }
                    arr.put(new org.json.JSONObject().put("type", type).put("typeValue", typeValue).put("conent", conent));

                }
                result.put("data", arr);
                logger.info(result.toString());
//                onetService.currentData(imei, dev_id, date,result.toString());
            }

        }
        return "ok";
    }


    @GetMapping("/kwyg")
    public String kwygcheck(@RequestParam(value = "msg") String msg,
                            @RequestParam(value = "nonce") String nonce,
                            @RequestParam(value = "signature") String signature) throws UnsupportedEncodingException {
        return chec(msg, nonce, signature);
    }

    @PostMapping("/zhuowen")
    public String zhuowen(@RequestBody String body)  throws JSONException {

        OneNetUtil.BodyObj resutl;
        if ((resutl = plain(body)) != null) {
            JSONObject json = JSON.parseObject(resutl.getMsg().toString());
            String imei = json.getString("imei");
            String dev_id = json.getString("dev_id");
            String at = TimeUtil.parseTime(LocalDateTime.ofEpochSecond(json.getLong("at"), 0, ZoneOffset.ofHours(8)));
            ;
            Integer type = json.getInteger("type");
            if (type == 1) {
//                { "msg":{"at":1581654972920,"imei":"860765046101462","type":1,"ds_id":"3200_0_5750",
//                "value":"{\"command\":\"POST-REALTIME\",\"content\":\"eyJicmVha2VycyI6eyIyMjAiOlsiMC4wMSIsIjI2LjMiLCIyMzcuMiIsIjAiLCIwIiwiMCIsIjEiLCI0OS45Il0sImJhc2UiOlsidjEuMCIsIlYxLjAiLCJaV0IxTEUtNjMvMlAiLCI2M0EiLCIxIiwibGluZTEiLCJjbG9zZSIsIjAiLCIwLjAiLCIwIiwiMCIsIjIyMCIsIjgwLFkiLCIyNjUsWSIsIjE2MCxOIiwiMTIwMDAsWSIsIjIxMjQsWSIsIjAsTiIsIjMwLFkiLCIiXX19\",\"check\":\"36F29772FDECFA5650FD0F4EC0CD3DEF\"}","dev_id":584602524}，"nonce":ji@ZuxfH，"signature":Gbn1CmEsClf9o+p6mf/PBA==}
//                {"breakers":{"220":["0.01","26.3","237.0","0","0","0","1","49.9"],"base":["v1.0","V1.0","ZWB1LE-63/2P","63A","1","line1","close","0","0.0","0","0","220","80,Y","265,Y","160,N","12000,Y","2124,Y","0,N","30,Y",""]}}
//                { "msg":{"at":1581655307183,"imei":"860765046101462","type":1,"ds_id":"3200_0_5750","value":"{\"command\":\"POST-REALTIME\",\"content\":\"eyJzZXJ2ZXJfaW5mbyI6WyJWMS4wLDAuOSIsInYxLjAiLCIiLCJKYW4gMTkgMjAyMCAxODoxNDo1MyJdfQ==\",\"check\":\"84F9F289B4A09FBB49A25704A8DD00DE\"}","dev_id":584602524}，"nonce":?c?Q8dQi，"signature":BCX+RXDpo8PfWE9hC20hfw==}
                JSONObject value = JSON.parseObject(json.getString("value"));
                String command = value.getString("command");
                String content = value.getString("content");
                String check = value.getString("check");


                String chec = "join-mcbs&" + content;
                String checMd5 = DigestUtils.md5DigestAsHex(chec.getBytes()).toUpperCase();
                if (!StringUtils.equals(checMd5, check)) {
                    logger.error("onenet zhuowen " + imei + "check no pass");
                    return "ok";
                }

                byte[] encMsg = Base64.decodeBase64(content);
                String pasecontent=new String(encMsg);
                logger.info("imei:{}==>content:{}",imei,pasecontent);
                if (StringUtils.equals(POST_REALTIME, command)) {
                    Map<Integer, ParamsSetting> desMap = paramsSettingService.findAll();
                    JSONObject entity = JSON.parseObject(pasecontent);
                    String serverInfo = entity.getString("server_info");
                    String breakers = entity.getString("breakers");
                    if (StringUtils.isNotEmpty(serverInfo)) {
                        List<String> list = JSONObject.parseArray(serverInfo, String.class);
                        String switch_electricCurrent = list.get(0);
                    }

                    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
                    String currentTime = dateFormat.format(new Date());

                    if (StringUtils.isNotEmpty(breakers)) {
                        JSONObject breakInfo = JSON.parseObject(breakers);
                        String base = breakInfo.getString("base");
                        String single = breakInfo.getString("220");
                        String three = breakInfo.getString("380");

                        List<BulkOperation> bulkOperationList = new ArrayList<>();
                        JsonObject insertJson = new JsonObject().put("imei", imei).put("createdAt", new JsonObject().put("$date", currentTime));
                        String currentTotal=null;
                        String switchStatus=null;

                        if (StringUtils.isNotEmpty(base)) {
                            List<String> list = JSONObject.parseArray(base, String.class);
                            String softwareVersion = list.get(0);
                            String hardwareVersion = list.get(1);
                            String emptyType = list.get(2);
                            String lineModel = list.get(3);
                            String lineAddress = list.get(4);
                            String lineName = list.get(5);
                            switchStatus = list.get(6);
                            String switchPatten = list.get(7);
                            currentTotal = list.get(8);
                            String powerCount = list.get(9);
                            String shortCount = list.get(10);
                            String lineType = list.get(11);


                            insertJson.put("lineType", lineType);
                            insertJson.put("deviceType", emptyType);
                            insertJson.put("deviceMode", lineModel);
                            insertJson.put("lineAddress", lineAddress);
                            insertJson.put("deviceId", imei+"-"+lineAddress);
                        }

                        if (StringUtils.isNotEmpty(three)) {
                            List<String> list = JSONObject.parseArray(three, String.class);
                            totalAndStatus(bulkOperationList, insertJson, desMap, currentTotal, switchStatus);

                            String a_electricCurrent = list.get(8);
                            splicMongo(a_electricCurrent, "A", 12, bulkOperationList, insertJson,desMap);
                            String a_temperature = list.get(9);
                            splicMongo(a_temperature, "℃", 130, bulkOperationList, insertJson,desMap);
                            String a_voltage = list.get(10);
                            splicMongo(a_voltage, "V", 9, bulkOperationList, insertJson,desMap);
                            double a_activePower = getConversion(list.get(11));
                            splicMongo(a_activePower, "kW", 16, bulkOperationList, insertJson,desMap);
                            double a_reactivePower = getConversion(list.get(12));
                            splicMongo(a_reactivePower, "kVar", 26, bulkOperationList, insertJson,desMap);
                            String a_powerFactor = list.get(13);
                            splicMongo(a_powerFactor, "", 20, bulkOperationList, insertJson,desMap);

                            String b_electricCurrent = list.get(14);
                            splicMongo(b_electricCurrent, "A", 13, bulkOperationList, insertJson,desMap);
                            String b_temperature = list.get(15);
                            splicMongo(b_temperature, "℃", 131, bulkOperationList, insertJson,desMap);
                            String b_voltage = list.get(16);
                            splicMongo(b_voltage, "V", 10, bulkOperationList, insertJson,desMap);
                            double b_activePower = getConversion(list.get(17));
                            splicMongo(b_activePower, "kW", 17, bulkOperationList, insertJson,desMap);
                            double b_reactivePower = getConversion(list.get(18));
                            splicMongo(b_reactivePower, "kVar", 27, bulkOperationList, insertJson,desMap);
                            String b_powerFactor = list.get(19);
                            splicMongo(b_powerFactor, "", 21, bulkOperationList, insertJson,desMap);

                            String c_electricCurrent = list.get(20);
                            splicMongo(c_electricCurrent, "A", 14, bulkOperationList, insertJson,desMap);
                            String c_temperature = list.get(21);
                            splicMongo(c_temperature, "℃", 132, bulkOperationList, insertJson,desMap);
                            String c_voltage = list.get(22);
                            splicMongo(c_voltage, "V", 11, bulkOperationList, insertJson,desMap);
                            double c_activePower = getConversion(list.get(23));
                            splicMongo(c_activePower, "kW", 18, bulkOperationList, insertJson,desMap);
                            double c_reactivePower = getConversion(list.get(24));
                            splicMongo(c_reactivePower, "kVar", 28, bulkOperationList, insertJson,desMap);
                            String c_powerFactor = list.get(25);
                            splicMongo(c_powerFactor, "", 22, bulkOperationList, insertJson,desMap);

                            try {
                                BigDecimal total_activePower = new BigDecimal(a_activePower).add(new BigDecimal(b_activePower)).add(new BigDecimal(c_activePower));
                                logger.debug("imei:{}==>{}==>{}==>{}", imei, a_activePower, b_activePower, c_activePower);
                                double v_activePower = total_activePower.setScale(2,RoundingMode.HALF_UP ).doubleValue();
                                splicMongo(v_activePower, "kW", 19, bulkOperationList, insertJson, desMap);
                                BigDecimal total_reactivePower = new BigDecimal(a_reactivePower).add(new BigDecimal(b_reactivePower)).add(new BigDecimal(c_reactivePower));
                                double v_reactivePower = total_reactivePower.setScale(2,RoundingMode.HALF_UP ).doubleValue();
                                splicMongo(v_reactivePower, "kVar", 29, bulkOperationList, insertJson, desMap);
                            }catch (Exception e){
                                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                                e.printStackTrace(new PrintStream(stream));
                                String exception = stream.toString();
                                logger.error(imei+"=exception="+exception);
                            }
                       }


                        if (StringUtils.isNotEmpty(single)) {
                            List<String> list = JSONObject.parseArray(single, String.class);
                            splicSingal(list, bulkOperationList, insertJson,desMap,currentTotal,switchStatus);
                        }

                        if (!bulkOperationList.isEmpty()) {
                            saveMongo("RealTimeData", bulkOperationList,imei);
                        }

                    }
                } else if (StringUtils.equals(command, POST_ALARM) ) {
                    //["1","line1","告警","5","N"]
                    List<String> list = JSONObject.parseArray(pasecontent, String.class);
                    JsonObject alarm = getEntries(list);
                    setJsonValue(list, alarm);
                    logger.debug("imei:{},alarm:{}",imei,alarm.toString());
                    try{
                        oneNETbefore.alarm(imei, alarm.toString());
                    }catch (Exception e){
                        logger.error("imei:{},onenet zhuowen alarm error:{}",imei,e.getMessage());
                    }



                }else if (StringUtils.equals(command, POST_WARN)) {
                    List<String> list = JSONObject.parseArray(pasecontent, String.class);
                    JsonObject police = getEntries(list);
                    setJsonValue(list, police);
                    logger.debug("imei:{},police:{}",imei,police.toString());
                    try{
                        oneNETbefore.police(imei, police.toString());
                    }catch (Exception e){
                        logger.error("imei:{},onenet zhuowen police error:{}",imei,e.getMessage());
                    }

                }else if (StringUtils.equals(command, POST_ALARM_DATA) ||StringUtils.equals(command, POST_WARN_DATA)) {
                    try{
                        OneNetCallBackResult oneNetCallBackResult = new OneNetCallBackResult();
                        oneNetCallBackResult.setImei(imei);
                        oneNetCallBackResult.setData(pasecontent);
                        oneNetCallBackResult.setCommand(command);
                        aPPoneNETbefore.cmdCallBack(oneNetCallBackResult);
                    }catch (Exception e){
                        logger.error("imei:{},onenet zhuowen cmdcallback error:{}",imei,e.getMessage());
                    }
                }
            }else {
//                {"at":1582272665867,"login_type":10,"imei":"860765046101462","type":2,"dev_id":584602524,"status":0}
                try{
                    oneNETbefore.changeState(imei, json.getInteger("status"));
                }catch (Exception e){
                    logger.error("imei:{},onenet zhuowen changeState error:{}",imei,e.getMessage());
                }

            }
        }
        return "ok";
    }

    private void setJsonValue(List<String> list, JsonObject police) {
        String v = "";
        for (int i = 6; i < list.size(); i++) {
            String s = list.get(i);
            if (StringUtils.isNotEmpty(s) && !StringUtils.equals(s, " ")) {
                v = s;
                break;
            }
        }
        police.put("value", v);
    }

    private JsonObject getEntries(List<String> list) {
        JsonObject alarm = new JsonObject();
        Map<String, Dictionaries> all = dictionariesService.findAll(OneNetCollectService.ZHUOWEN);
        String id=list.get(3);
        Dictionaries policeype=all.get(id);
        if(policeype!=null){
           alarm.put("type", policeype.getType());
       }else {
            alarm.put("type", id);
       }
        alarm.put("lineAddr", list.get(0));
        alarm.put("lineName", list.get(1));
        alarm.put("policeType", list.get(2));
        alarm.put("isSynServer", list.get(4));
        alarm.put("lineType", list.get(5));
        return alarm;
    }

    public void  splicSingal(List<String> list,List<BulkOperation> bulkOperationList,JsonObject insertJson,Map<Integer, ParamsSetting> desMap,String currentTotal,String switchStatus){

        totalAndStatus(bulkOperationList, insertJson, desMap, currentTotal, switchStatus);
        String switch_electricCurrent = list.get(0);
        splicMongo(switch_electricCurrent,"A",120,bulkOperationList,insertJson,desMap);
        String switch_temperature = list.get(1);
        splicMongo(switch_temperature,"℃",121,bulkOperationList,insertJson,desMap);
        String switch_voltage = list.get(2);
        splicMongo(switch_voltage,"V",122,bulkOperationList,insertJson,desMap);
        double switch_activePower = getConversion(list.get(3));
        splicMongo(switch_activePower,"kW",123,bulkOperationList,insertJson,desMap);
        double switch_reactivePower = getConversion(list.get(4));
        splicMongo(switch_reactivePower,"kVar",124,bulkOperationList,insertJson,desMap);
//        String switch_electricLeakage = list.get(5);
//        splicMongo(switch_electricLeakage,"mA",125,bulkOperationList,insertJson,desMap);
        String switch_powerFactor = list.get(6);
        splicMongo(switch_powerFactor,"",126,bulkOperationList,insertJson,desMap);
        String switch_frequency = list.get(7);
        splicMongo(switch_frequency,"Hz",127,bulkOperationList,insertJson,desMap);
    }

    private void totalAndStatus(List<BulkOperation> bulkOperationList, JsonObject insertJson, Map<Integer, ParamsSetting> desMap, String currentTotal, String switchStatus) {
        if(StringUtils.equals(switchStatus, "close")){
            splicMongo("0","",205,bulkOperationList,insertJson,desMap);
        }else {
            splicMongo("1","",205,bulkOperationList,insertJson,desMap);
        }
        splicMongo(getConversion(currentTotal),"kWh",4,bulkOperationList,insertJson,desMap);
    }

    private double  getConversion(String value){
       BigDecimal bd=new BigDecimal(value);
       BigDecimal divide = bd.divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP);
       return divide.doubleValue();
   }

    public  void  splicMongo(Object value,String unit,int type,List<BulkOperation> bulkOperationList,JsonObject json,Map<Integer, ParamsSetting>  desMap){
        JsonObject copy = json.copy();
        copy.put("value",value);
        copy.put("type",type);
        copy.put("unit",unit);
        if(desMap.get(type)!=null){
            copy.put("des",desMap.get(type).getDes());
        }
        bulkOperationList.add(BulkOperation.createInsert(copy));
    }

    public void saveMongo(String saveName, List<BulkOperation> bulkOperationList,String imei) {
        mongoClient.bulkWrite(saveName, bulkOperationList, stringAsyncResult -> {
            if (stringAsyncResult.succeeded()) {
                com.alibaba.fastjson.JSONArray data= bulkOperationList.stream().map((b) ->{
                    return b.getDocument().getString("_id");
                }).collect(Collectors.toCollection(com.alibaba.fastjson.JSONArray::new));

                try{
                    oneNETbefore.data(imei, data.toString());
                }catch (Exception e){
                    logger.error("onenet saveMongoAndSend rpc data invoke faile:{}",e.getMessage());
                }
            } else {
                logger.error("monggoDB onenet save faile： " + stringAsyncResult.cause().getMessage() +   "==>" );
            }

        });
    }

    @GetMapping("/zhuowen")
    public String zhuowen(@RequestParam(value = "msg") String msg,
                            @RequestParam(value = "nonce") String nonce,
                            @RequestParam(value = "signature") String signature) throws UnsupportedEncodingException {
        return chec(msg, nonce, signature);
    }

    @PostMapping("/kwyg")
    public String kwygreceive(@RequestBody String body)  throws JSONException {

        OneNetUtil.BodyObj resutl;
        if((resutl=plain(body))!=null) {
//            {"msg":{"at":1574406794462,"imei":"869975030507381","type":1,"ds_id":"3200_0_5750",
//                    "value":"KW|KAIWAN|460042567812043&869975030507381|2019/11/22,15:13:12GMT+8|01|00|03|00|200.00|04|00|200.00|05|00|20100|06|00|0010|07|00|200.00|6F06","dev_id":571480326}
//            ,"msg_signature":"dKTBTkHitlqklIAj+JsCVw==","nonce":"BRxC=g!S"}
//            {"msg":{"at":1574406725907,"login_type":10,"imei":"869975030507381","type":2,"dev_id":571480326,"status":1},"msg_signature":"icJuwNQOkP+By5EraWb42A==","nonce":"AG_9Gd?w"}
            JSONObject json = JSON.parseObject(resutl.getMsg().toString());
            String value = json.getString("value");
            if (value != null) {
                String[] split = value.split("\\|");
                if (StringUtils.equals(split[4],"01")  ) {
                    StringBuilder sb = new StringBuilder("KW|KAIWAN");
                    sb.append("|" + split[2]);
                    if( StringUtils.equals(split[5],"00")){
                        sb.append("|F1|01-02-10-10|03|01|2-20.3|04|01|4-10|");
                    }else if(StringUtils.equals(split[5],"01")){
                        sb.append("|F2|01|");
                    }else if(StringUtils.equals(split[5],"01")){
                        sb.append("|F2|03|");
                    }
                    String crc = CRC_XModem(sb.toString().getBytes());
                    sb.append(crc);
                    logger.info(sb.toString() + "---------------------------------------------------------");
                    String[] ds_id = json.getString("ds_id").split("_");
                    String resu = null;
                    try {
                        resu = oneNetCollectService.executeCmd(sb.toString(), json.getString("imei"), "SMOKE");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    logger.info(resu);
//                    ExecuteOpe executeOpe = new ExecuteOpe(kwyapiKey);
//                    Execute execute = new Execute(json.getString("imei"), Integer.parseInt(ds_id[0]), Integer.parseInt(ds_id[1]), Integer.parseInt(ds_id[2]));
//                    org.json.JSONObject params = new org.json.JSONObject();
//                    params.put("args", sb.toString());
//                    logger.info(executeOpe.operation(execute, params).toString());
                }
            }
        }
        return "ok";
    }

    public String chec(String msg,String nonce,String signature) throws UnsupportedEncodingException {
        logger.info("url&token check: msg:{} nonce:{} signature:{}",msg,nonce,signature);
        if (OneNetUtil.checkToken(msg,nonce,signature,token)){
            return msg;
        }else {
            return "error";
        }
    }

    public static String CRC_XModem(byte[] bytes) {
        int crc =0xA1EC;          // initial value
        int polynomial = 0x1021;
        for (int index = 0; index < bytes.length; index++) {
            byte b = bytes[index];
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7 - i) & 1) == 1);
                boolean c15 = ((crc >> 15 & 1) == 1);
                crc <<= 1;
                if (c15 ^ bit) {crc ^= polynomial;}
            }
        }
        crc &= 0xffff;
        String refCrc = Integer.toHexString(crc).toUpperCase();
        if (refCrc.length() == 3) {
            refCrc = "0" + refCrc;
        }
        if (refCrc.length() == 2) {
            refCrc = "00" + refCrc;
        }
        return refCrc;
    }

    public OneNetUtil.BodyObj plain(String body){

        logger.info("data receive:  body String --- " +body);
        /************************************************
         *  解析数据推送请求，非加密模式。
         *  如果是明文模式使用以下代码
         **************************************************/
        /*************明文模式  start****************/
        OneNetUtil.BodyObj obj = OneNetUtil.resolveBody(body, false);
        if (obj != null){
            boolean dataRight = OneNetUtil.checkSignature(obj, token);
            if (dataRight){
//                logger.info("data receive: content" + obj.toString());
                return obj;
            }else {
                logger.info("data receive: signature error");
            }

        }else {
            logger.info("data receive: body empty error");
        }
        /*************明文模式  end****************/


        /********************************************************
         *  解析数据推送请求，加密模式
         *
         *  如果是加密模式使用以下代码
         ********************************************************/
        /*************加密模式  start****************/
//        Util.BodyObj obj1 = Util.resolveBody(body, true);
//        logger.info("data receive:  body Object--- " +obj1);
//        if (obj1 != null){
//            boolean dataRight1 = Util.checkSignature(obj1, token);
//            if (dataRight1){
//                String msg = Util.decryptMsg(obj1, aeskey);
//                logger.info("data receive: content" + msg);
//            }else {
//                logger.info("data receive:  signature error " );
//            }
//        }else {
//            logger.info("data receive: body empty error" );
//        }
        /*************加密模式  end****************/
        return null;
    }
}
